package edu.whu.irlab.entry;

import com.google.common.base.Strings;
import edu.whu.irlab.db.dao.BaseDao;
import edu.whu.irlab.entity.Posting;
import edu.whu.irlab.entity.Task;
import edu.whu.irlab.util.time.Timer;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by zhongwei on 2017/5/27.
 */
public class Entry {

    static BaseDao baseDao = new BaseDao();
    static boolean clicked = false;
    static int counter = 0;
    private static WebDriver driver;
    private static boolean terminated = false;
    private static String taskStr;
    private static Set<Posting> set = new HashSet<>();
    private static int taskCounter = 1;

    public static void main(String[] args) throws IOException {
        List<Task> taskList = baseDao.find("from Task where done=0");
        //System.setProperty("webdriver.firefox.bin", "C:\\Program Files\\Mozilla Firefox\\firefox.exe");
        System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
        //System.setProperty("webdriver.ie.driver", "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe");
        URL url = ClassLoader.getSystemResource("gecko/geckodriver.exe");
        System.setProperty("webdriver.gecko.driver", url.getPath());
        List<String> userNameAndPassword = FileUtils.readLines(new File("users.txt"));
        String userName = userNameAndPassword.get(0);
        String password = userNameAndPassword.get(1);
        driver = new ChromeDriver();
        try {
            Thread.currentThread().sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
        //driver.manage().timeouts().setScriptTimeout(3, TimeUnit.SECONDS);
        login(driver, userName, password);
        for (Task task : taskList) {
            taskStr = task.getUrl();
            openDetailPage(driver, taskStr);
            task.setDone(1);
            baseDao.update(task);
            taskCounter++;
        }
        driver.quit();
    }

    private static void login(WebDriver driver, String userName, String password) {
        driver.get("http://weibo.com/");
        WebElement userNameEle = tryFind(driver, By.id("loginname"));
        WebElement passwordEle = tryFind(driver, By.xpath("//*[@id=\"pl_login_form\"]/div/div[3]/div[2]/div/input"));
        tryClick(driver, userNameEle);
        userNameEle.clear();
        trySend(userNameEle, userName);
        tryClick(driver, passwordEle);
        passwordEle.clear();
        trySend(passwordEle, password);
        WebElement inputButtonEle = tryFind(driver, By.xpath("//*[@id=\"pl_login_form\"]/div/div[3]/div[6]/a"));
        try {
            inputButtonEle.click();
            //driver.manage().timeouts().pageLoadTimeout(1, TimeUnit.MINUTES);
        } catch (Exception e) {
            // ignore
        }
    }

    static void trySend(WebElement element, String key) {
        try {
            element.sendKeys(key);
        } catch (Exception e) {
            trySend(element, key);
        }
    }

    private static void openDetailPage(WebDriver driver, String link) {
        tryGet(driver, link);
        while (true) {
            if (terminated == true)
                return;
            if (!clicked) {
                while (true) {
                    List<WebElement> aList = driver.findElements(By.className("S_txt1"));
                    for (WebElement element : aList) {
                        if (element.getText().trim().equals("全部")) {
                            tryClick(driver, element);
                            clicked = true;
                            break;
                        }
                    }
                    if (clicked == true)
                        break;
                }
            }
            //y坐标一直移动到100000，如果中途发现下一页链接则成功，否则失败，翻页结束
            int yAxis = 10000;
            while (true) {
                if (terminated == true)
                    return;
                if (driver.getPageSource().contains("请求超时")) {
                    List<WebElement> weiboWraps = driver.findElements(By.className("WB_innerwrap"));
                    for (WebElement element : weiboWraps) {
                        if (element.getText().contains("请求超时")) {
                            element.click();
                        }
                    }
                }
                yAxis += 10000;
                String yAxisStr = String.valueOf(yAxis);
                ((JavascriptExecutor) driver).executeScript("scroll(0," + yAxisStr + ");");
                if (findNextPage(driver))
                    break;
                else {
                    if (yAxis >= 100000) {
                        System.out.println("翻页结束");
                        break;
                    }
                }
            }
        }
    }

    private static boolean findNextPage(WebDriver driver) {
        WebElement wpages = null;
        try {
            wpages = driver.findElement(By.className("W_pages"));
        } catch (Exception e) {
            return false;
            //
        }
        List<WebElement> aList = wpages.findElements(By.tagName("a"));
        WebElement nextEle = aList.get(aList.size() - 1);
        parse(driver);
        if (nextEle.getText().equals("下一页")) {
            tryClick(driver, nextEle);
            return true;
        } else return false;
    }

    private static WebElement tryFind(WebDriver driver, By by) {
        try {
            return driver.findElement(by);
        } catch (Exception e) {
            return tryFind(driver, by);
        }
    }

    private static void tryClick(WebDriver driver, WebElement element) {
        try {
            element.click();
        } catch (Exception e) {
            tryClick(driver, element);
        }
    }

    private static void tryGet(WebDriver driver, String link) {
        try {
            driver.get(link);
        } catch (Exception e) {
            tryGet(driver, link);
//            System.err.println(link + " : 超时");
        }
    }

    private static void parse(WebDriver driver) {
        List<WebElement> weibos = driver.findElements(By.className("WB_cardwrap"));
        for (WebElement weibo : weibos) {
            if (terminated == true)
                return;
            try {
                String posterName = weibo.findElement(By.className("WB_info")).getText();
                String timeStr = weibo.findElement(By.className("WB_from")).getText();
                String textContent = weibo.findElement(By.className("WB_text")).getText();
                WebElement weiboBox = weibo.findElement(By.className("WB_media_a"));
                List<WebElement> picEles = weiboBox.findElements(By.tagName("li"));
                StringBuilder stringBuilder = new StringBuilder();
                for (WebElement ele : picEles) {
                    String aLink = ele.findElement(By.tagName("img")).getAttribute("src");
                    stringBuilder.append(aLink + ";");
                }
                List<WebElement> aList = weibo.findElement(By.className("WB_handle")).findElements(By.tagName("li"));
                String repostNumStr = aList.get(1).getText();
                String commentStr = aList.get(2).getText();
                String likeStr = aList.get(3).getText();
                Date time = parseTime(timeStr);
                Posting posting = new Posting();
                posting.setPosterName(posterName);
                posting.setLikeNum(likeStr);
                posting.setRepostNum(repostNumStr);
                posting.setCommentNum(commentStr);
                posting.setImageUrls(stringBuilder.toString());
                posting.setTextContent(textContent);
                posting.setTime(time);
                posting.setFromUrl(taskStr);
                if (set.contains(posting)) {

                    continue;
                }
                baseDao.create(posting);
                System.out.println("第" + taskCounter + "条任务的第" + counter + "条记录。");
                if (!Strings.isNullOrEmpty(posting.getImageUrls()))
                    counter++;
                if (counter >= 510) {
                    terminated = true;
                }
            } catch (Exception e) {
                //ignore
            }
        }
    }

    private static Date parseTime(String text) {
        Pattern pattern = Pattern.compile("(\\d{1,2})月(\\d{1,2})日 (\\d{1,2}):(\\d{1,2})");
        Matcher matcher = pattern.matcher(text);
        if (matcher.find()) {
            String monthStr = matcher.group(1);
            String dayStr = matcher.group(2);
            String hourStr = matcher.group(3);
            String minuteStr = matcher.group(4);
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.YEAR, 2017);
            calendar.set(Calendar.MONTH, Integer.parseInt(monthStr));
            calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dayStr));
            calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hourStr));
            calendar.set(Calendar.MINUTE, Integer.parseInt(minuteStr));
            return calendar.getTime();
        }
        try {
            return new Date(Timer.standard(text).getTime());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
